//
//  MultiTouch2OSC
//  2009 Michael Gubik.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


#import "AppController.h"
#import "MTRespondingView.h"
#import "MTVisualizingView.h"

@implementation AppController

@synthesize lockForCompositionInput;

#pragma mark Lifecycle

- (id) init	{
	if (self = [super init])	{
		oscManager = [[OSCManager alloc] init];
		outPort = [oscManager createNewOutputToAddress:@"127.0.0.1" atPort:57120];
		if (outPort == nil)
			NSLog(@"error creating output");

		touchDicts = [[NSMutableArray alloc] init];
	}
	
	return self;
}

- (void) awakeFromNib {
	[window setBackgroundColor:[NSColor colorWithDeviceWhite:0.0 alpha:.14]];
	[window setOpaque:NO];		
	isInFullScreenMode = NO;
	
	multiTouchVisualizingView = [[MTVisualizingView alloc] initWithFrame:[multiTouchRespondingView frame]];
	[multiTouchRespondingView addSubview:multiTouchVisualizingView];
	[multiTouchRespondingView setAutoresizesSubviews:YES];

	
	[multiTouchRespondingView addObserver:self
							   forKeyPath:@"touchArray"
								  options:0
								  context:NULL];
	
	lockForCompositionInput = [[NSLock alloc] init];

	myThread = [[NSThread alloc] initWithTarget:multiTouchVisualizingView
									   selector:@selector(prepareRendererAndOpenGLContextThenStartRendering)
										 object:nil];
	[myThread start];
	
	[window makeFirstResponder:multiTouchRespondingView];

}

#pragma mark Observation and QC 

- (void)observeValueForKeyPath:(NSString *)keyPath
					  ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqual:@"touchArray"]){
		[self packAndSendOSCMessage];
		[self updateCompositionWithTouchArray:[multiTouchRespondingView touchArray]];
	}
}


- (void)updateCompositionWithTouchArray:(NSArray *)touchArray {

	[lockForCompositionInput lock];
	[touchDicts release];
	
	touchDicts = [[NSMutableArray alloc] initWithCapacity:[touchArray count]];

	
	for (NSTouch *touch in touchArray) {
		if ([touch isEqual:[NSNull null]]) {
			[touchDicts addObject:[NSDictionary dictionaryWithObjectsAndKeys:
								   [NSNumber numberWithDouble:0.0], @"x",
								   [NSNumber numberWithDouble:0.0], @"y",
								   [NSNumber numberWithBool:NO], @"active",
								   nil]];
		} else {
			[touchDicts addObject:[NSDictionary dictionaryWithObjectsAndKeys:
								   [NSNumber numberWithDouble:touch.normalizedPosition.x], @"x",
								   [NSNumber numberWithDouble:touch.normalizedPosition.y], @"y",
								   [NSNumber numberWithBool:YES], @"active",
								   nil]];
		}
	}

	[touchDicts retain];
	[[multiTouchVisualizingView mainRenderer] setValue:touchDicts forInputKey:@"touches"];
	[lockForCompositionInput unlock];


}

#pragma mark OSC Sending

- (void)packAndSendOSCMessage
{
	OSCMessage *flatTAMsg = [OSCMessage createWithAddress:@"/multiTouch/flatTouchArray"];
	
	NSArray *touchArray = [multiTouchRespondingView touchArray];

	for (NSTouch *touch in touchArray) {
		if ([touch isEqual:[NSNull null]]) {
			[flatTAMsg addFloat:(float)0.0];
			[flatTAMsg addFloat:(float)0.0];
			[flatTAMsg addInt:0];
		} else {
			[flatTAMsg addFloat:(float)touch.normalizedPosition.x];
			[flatTAMsg addFloat:(float)touch.normalizedPosition.y];
			[flatTAMsg addInt:1];
		}
	}
	
	
	OSCPacket *pack = [OSCPacket createWithContent:flatTAMsg];
	[outPort sendThisPacket:pack];		
}

#pragma mark Actions

- (IBAction)changeIPAddressAndPort:(id)sender {
	unsigned short newPort;
	NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
	NSNumber *n = [numberFormatter numberFromString:[portTextField stringValue]];
	newPort = [n unsignedShortValue];
	[numberFormatter release];

	
	if ( newPort != [outPort port] )
		[outPort setPort:newPort];
	
	[outPort setPort:[portTextField intValue]];
	
	NSString *newIP = [ipAddressTextField stringValue];
	if ( ![[outPort addressString] isEqualToString:newIP] )
		[outPort setAddressString:newIP];
	
//	printf("%i", newPort);
	
}

- (IBAction)setIPAddressToLocalhost:(id)sender {
	[ipAddressTextField setStringValue:@"127.0.0.1"];
	[self changeIPAddressAndPort:self];
}


#pragma mark UI Window Handling
                                                                          
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize {     
	[multiTouchVisualizingView resize];                        
	return frameSize;                                                          
}

- (IBAction)toggleFullScreen:(id)sender
{
	if ( isInFullScreenMode == NO ) {
		windowRectForNonFullScreenMode = [window frame]; // save frame rect
		[window setStyleMask:NSBorderlessWindowMask];
		[window setFrame:[[NSScreen mainScreen] frame] display:YES];
		[window setLevel:NSScreenSaverWindowLevel];
		CGDisplayHideCursor(kCGDirectMainDisplay);
		[window makeFirstResponder:multiTouchRespondingView];
		[multiTouchVisualizingView resize];
		isInFullScreenMode = YES;
		
	} else {
		[window setStyleMask:(NSTitledWindowMask|NSClosableWindowMask|NSResizableWindowMask)];
		[window setFrame:windowRectForNonFullScreenMode display:YES];
		[window setTitle:@"Touch Event Receiving Window    ( ⌘F Full Screen  |  ⌘, OSC Preferences )"];
		[window setLevel:NSNormalWindowLevel];
		CGDisplayShowCursor(kCGDirectMainDisplay);
		[multiTouchVisualizingView resize];
		isInFullScreenMode = NO;
	}
}

- (void)keyDown:(NSEvent *)theEvent {
	if ([theEvent keyCode] == 0x35 && isInFullScreenMode) {
		[self toggleFullScreen:self];
	}
	//[super keyDown:theEvent];
}


// for cmd-tab'ing away from app in full screen mode
- (void)applicationDidResignActive:(NSNotification *)aNotification {
	[window setLevel:NSNormalWindowLevel];

}
- (void)applicationWillBecomeActive:(NSNotification *)aNotification {
	if ( isInFullScreenMode )
		[window setLevel:NSScreenSaverWindowLevel];
	[window makeFirstResponder:multiTouchRespondingView];
}

- (void)windowWillClose:(NSNotification *)notification  {
	[NSApp terminate:self];
}

@end
